šŸ“š Lecture 8: Arrays and Types of Arrays

Understanding Data Structures in Java

← Back to Course

šŸŽÆ Introduction to Arrays

An array is a fundamental data structure in Java that allows you to store multiple values of the same type in a single variable. Arrays are fixed-size collections where each element can be accessed using an index. They provide an efficient way to organize and manipulate related data items.

Key Definition: An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created, and after creation, its length is fixed.

Why Use Arrays?

  • Efficient Storage: Arrays store elements in contiguous memory locations, making access fast and efficient.
  • Random Access: Elements can be accessed directly using their index in O(1) time complexity.
  • Organization: Groups related data together, making code more organized and readable.
  • Memory Management: Fixed size helps in predictable memory allocation.

šŸ“Š Array Basics

Declaring Arrays

In Java, arrays can be declared in two ways:

Method 1: dataType[] arrayName;
Method 2: dataType arrayName[];
// Array declarations int[] numbers; // Preferred method String names[]; // Alternative method double[] prices; boolean[] flags; char[] characters;

Creating and Initializing Arrays

// Method 1: Declare and create separately int[] numbers = new int[5]; // Creates array of size 5 with default values (0) // Method 2: Declare and initialize int[] scores = {90, 85, 78, 92, 88}; // Method 3: Create and then assign String[] fruits = new String[3]; fruits[0] = "Apple"; fruits[1] = "Banana"; fruits[2] = "Orange";

Array Indexing

Array indices start from 0 and go up to (length - 1). Attempting to access an index outside this range results in an ArrayIndexOutOfBoundsException.

10
25
15
30
20

šŸ”¢ Types of Arrays

1. Single-Dimensional Arrays

The most common type of array, representing a linear list of elements.

// Single-dimensional array example public class SingleArrayExample { public static void main(String[] args) { int[] temperatures = {23, 25, 19, 30, 28, 22}; // Accessing elements System.out.println("First temperature: " + temperatures[0]); System.out.println("Last temperature: " + temperatures[temperatures.length - 1]); // Iterating through array for (int i = 0; i < temperatures.length; i++) { System.out.println("Day " + (i + 1) + ": " + temperatures[i] + "°C"); } // Enhanced for loop for (int temp : temperatures) { System.out.println("Temperature: " + temp + "°C"); } } }

2. Multi-Dimensional Arrays

Arrays of arrays, useful for representing tables, matrices, or grid-like data structures.

// Two-dimensional array example public class MultiArrayExample { public static void main(String[] args) { // 2D array representing a matrix int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; // Accessing elements System.out.println("Element at [0][1]: " + matrix[0][1]); // Iterating through 2D array for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); } } }

3. Jagged Arrays

Arrays where each sub-array can have different lengths. Also known as ragged arrays.

// Jagged array example public class JaggedArrayExample { public static void main(String[] args) { // Jagged array where each row has different length int[][] jaggedArray = new int[3][]; jaggedArray[0] = new int[2]; // First row has 2 elements jaggedArray[1] = new int[4]; // Second row has 4 elements jaggedArray[2] = new int[3]; // Third row has 3 elements // Initialize with values jaggedArray[0] = {1, 2}; jaggedArray[1] = {3, 4, 5, 6}; jaggedArray[2] = {7, 8, 9}; // Display jagged array for (int i = 0; i < jaggedArray.length; i++) { for (int j = 0; j < jaggedArray[i].length; j++) { System.out.print(jaggedArray[i][j] + " "); } System.out.println(); } } }

⚔ Array Operations

Common Array Operations

public class ArrayOperations { public static void main(String[] args) { int[] numbers = {5, 2, 8, 1, 9, 3}; // 1. Finding the length System.out.println("Array length: " + numbers.length); // 2. Finding maximum and minimum int max = numbers[0]; int min = numbers[0]; for (int num : numbers) { if (num > max) max = num; if (num < min) min = num; } System.out.println("Maximum: " + max); System.out.println("Minimum: " + min); // 3. Calculating sum int sum = 0; for (int num : numbers) { sum += num; } System.out.println("Sum: " + sum); System.out.println("Average: " + (double)sum / numbers.length); // 4. Searching for an element int target = 8; boolean found = false; for (int i = 0; i < numbers.length; i++) { if (numbers[i] == target) { System.out.println(target + " found at index " + i); found = true; break; } } if (!found) { System.out.println(target + " not found in the array"); } } }

Sorting Arrays

import java.util.Arrays; public class ArraySorting { public static void main(String[] args) { int[] numbers = {5, 2, 8, 1, 9, 3}; // Using built-in sort method Arrays.sort(numbers); System.out.println("Sorted array: " + Arrays.toString(numbers)); // Manual bubble sort int[] unsorted = {5, 2, 8, 1, 9, 3}; bubbleSort(unsorted); System.out.println("Bubble sorted: " + Arrays.toString(unsorted)); } public static void bubbleSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { // Swap elements int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } }

šŸ“ˆ Array Performance and Characteristics

Operation Time Complexity Description
Access by Index O(1) Direct access to any element using its index
Search (Linear) O(n) Searching for an element by value
Insertion O(n) Requires shifting elements (not efficient for arrays)
Deletion O(n) Requires shifting elements (not efficient for arrays)
Memory Usage O(n) Contiguous memory allocation

āœ… Advantages

  • Fast random access (O(1))
  • Memory efficient due to contiguous storage
  • Simple to use and understand
  • Good cache performance
  • Type safety at compile time

āŒ Limitations

  • Fixed size (cannot grow or shrink)
  • Expensive insertion/deletion operations
  • All elements must be of same type
  • Cannot store mixed data types
  • Wasted memory if underutilized

šŸŽÆ Practical Examples

Example 1: Student Grade Management

public class StudentGrades { public static void main(String[] args) { // Array to store student grades double[] grades = {85.5, 92.0, 78.5, 88.0, 91.5, 76.0, 89.5}; // Calculate statistics double average = calculateAverage(grades); double highest = findHighest(grades); double lowest = findLowest(grades); System.out.println("Grade Statistics:"); System.out.println("Average: " + average); System.out.println("Highest: " + highest); System.out.println("Lowest: " + lowest); // Count grades above average int aboveAverage = 0; for (double grade : grades) { if (grade > average) { aboveAverage++; } } System.out.println("Students above average: " + aboveAverage); } public static double calculateAverage(double[] grades) { double sum = 0; for (double grade : grades) { sum += grade; } return sum / grades.length; } public static double findHighest(double[] grades) { double highest = grades[0]; for (double grade : grades) { if (grade > highest) { highest = grade; } } return highest; } public static double findLowest(double[] grades) { double lowest = grades[0]; for (double grade : grades) { if (grade < lowest) { lowest = grade; } } return lowest; } }

Example 2: Matrix Operations

public class MatrixOperations { public static void main(String[] args) { int[][] matrixA = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; int[][] matrixB = { {9, 8, 7}, {6, 5, 4}, {3, 2, 1} }; // Matrix addition int[][] result = addMatrices(matrixA, matrixB); System.out.println("Matrix Addition Result:"); printMatrix(result); // Matrix transpose int[][] transpose = transposeMatrix(matrixA); System.out.println("\nTranspose of Matrix A:"); printMatrix(transpose); } public static int[][] addMatrices(int[][] a, int[][] b) { int rows = a.length; int cols = a[0].length; int[][] result = new int[rows][cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { result[i][j] = a[i][j] + b[i][j]; } } return result; } public static int[][] transposeMatrix(int[][] matrix) { int rows = matrix.length; int cols = matrix[0].length; int[][] transpose = new int[cols][rows]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { transpose[j][i] = matrix[i][j]; } } return transpose; } public static void printMatrix(int[][] matrix) { for (int[] row : matrix) { for (int element : row) { System.out.print(element + "\t"); } System.out.println(); } } }

šŸ” Common Array Methods and Utilities

Java Arrays Class

Java provides the java.util.Arrays class with various utility methods for array operations:

import java.util.Arrays; public class ArrayUtilities { public static void main(String[] args) { int[] numbers = {5, 2, 8, 1, 9, 3}; // Convert array to string System.out.println("Array: " + Arrays.toString(numbers)); // Sort array Arrays.sort(numbers); System.out.println("Sorted: " + Arrays.toString(numbers)); // Binary search (array must be sorted first) int index = Arrays.binarySearch(numbers, 8); System.out.println("Index of 8: " + index); // Fill array with specific value int[] filledArray = new int[5]; Arrays.fill(filledArray, 7); System.out.println("Filled array: " + Arrays.toString(filledArray)); // Copy array int[] copiedArray = Arrays.copyOf(numbers, numbers.length); System.out.println("Copied array: " + Arrays.toString(copiedArray)); // Compare arrays boolean equal = Arrays.equals(numbers, copiedArray); System.out.println("Arrays equal: " + equal); } }

Common Array Pitfalls

āš ļø ArrayIndexOutOfBoundsException: Always ensure array indices are within bounds (0 to length-1).
āš ļø Null Pointer Exception: Array references can be null if not initialized.
āš ļø Fixed Size Limitation: Arrays cannot be resized. Use ArrayList for dynamic sizing needs.

šŸ“ Summary

Arrays are fundamental data structures in Java that provide efficient storage and access to homogeneous data collections. We've covered single-dimensional arrays for linear data, multi-dimensional arrays for tabular data, and jagged arrays for variable-length sub-arrays.

Key takeaways include understanding array declaration and initialization, proper indexing, common operations like searching and sorting, and the performance characteristics that make arrays suitable for certain use cases while limiting them for others.

While arrays provide excellent performance for random access and are memory efficient due to contiguous storage, their fixed size limitation makes them less suitable for scenarios requiring dynamic data growth. For such cases, Java's Collection framework provides alternatives like ArrayList.

Mastering arrays is essential for any Java programmer as they form the foundation for understanding more complex data structures and are widely used in various applications from simple data storage to complex algorithms and matrix operations.

šŸ“ Practice Questions

1. Multiple Choice

What is the time complexity for accessing an element in an array by its index?

2. True or False

Arrays in Java can dynamically change their size after creation.


3. Short Answer

Explain the difference between a regular 2D array and a jagged array in Java.

4. Coding Exercise

Write a Java method that finds and returns the second largest element in an integer array.